{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "spare-academy",
   "metadata": {},
   "source": [
    "## Traefik Examples\n",
    "\n",
    "Assumes\n",
    "\n",
    " * You have installed Traefik as per their [docs](https://doc.traefik.io/traefik/getting-started/install-traefik/#use-the-helm-chart) into namespace traefik-v2\n",
    " \n",
    " Tested with traefik-10.19.4\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "other-sweden",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'172.21.255.1'"
      ]
     },
     "execution_count": 1,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "INGRESS_IP=!kubectl get svc traefik -n traefik-v2 -o jsonpath='{.status.loadBalancer.ingress[0].ip}'\n",
    "INGRESS_IP=INGRESS_IP[0]\n",
    "import os\n",
    "os.environ['INGRESS_IP'] = INGRESS_IP\n",
    "INGRESS_IP"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "bizarre-classification",
   "metadata": {},
   "source": [
    "### Traefik Single Model Example"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "realistic-marshall",
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "apiVersion: v1\r\n",
      "kind: Service\r\n",
      "metadata:\r\n",
      "  name: myapps\r\n",
      "  namespace: seldon-mesh\r\n",
      "spec:\r\n",
      "  ports:\r\n",
      "  - name: web\r\n",
      "    port: 80\r\n",
      "    protocol: TCP\r\n",
      "  selector:\r\n",
      "    app: traefik-ingress-lb\r\n",
      "  type: LoadBalancer\r\n",
      "---\r\n",
      "apiVersion: mlops.seldon.io/v1alpha1\r\n",
      "kind: Model\r\n",
      "metadata:\r\n",
      "  name: iris\r\n",
      "  namespace: seldon-mesh\r\n",
      "spec:\r\n",
      "  requirements:\r\n",
      "  - sklearn\r\n",
      "  storageUri: gs://seldon-models/mlserver/iris\r\n",
      "---\r\n",
      "apiVersion: traefik.containo.us/v1alpha1\r\n",
      "kind: IngressRoute\r\n",
      "metadata:\r\n",
      "  name: iris\r\n",
      "  namespace: seldon-mesh\r\n",
      "spec:\r\n",
      "  entryPoints:\r\n",
      "  - web\r\n",
      "  routes:\r\n",
      "  - kind: Rule\r\n",
      "    match: PathPrefix(`/`)\r\n",
      "    middlewares:\r\n",
      "    - name: iris-header\r\n",
      "    services:\r\n",
      "    - name: seldon-mesh\r\n",
      "      port: 80\r\n",
      "      scheme: h2c\r\n",
      "---\r\n",
      "apiVersion: traefik.containo.us/v1alpha1\r\n",
      "kind: Middleware\r\n",
      "metadata:\r\n",
      "  name: iris-header\r\n",
      "  namespace: seldon-mesh\r\n",
      "spec:\r\n",
      "  headers:\r\n",
      "    customRequestHeaders:\r\n",
      "      seldon-model: iris\r\n"
     ]
    }
   ],
   "source": [
    "!kustomize build config/single-model"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "variable-departure",
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "service/myapps created\n",
      "model.mlops.seldon.io/iris created\n",
      "ingressroute.traefik.containo.us/iris created\n",
      "middleware.traefik.containo.us/iris-header created\n"
     ]
    }
   ],
   "source": [
    "!kustomize build config/single-model | kubectl apply -f -"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "growing-writing",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "model.mlops.seldon.io/iris condition met\r\n"
     ]
    }
   ],
   "source": [
    "!kubectl wait --for condition=ready --timeout=300s model --all -n seldon-mesh"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "intelligent-dynamics",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "*   Trying 172.21.255.1...\n",
      "* Connected to 172.21.255.1 (172.21.255.1) port 80 (#0)\n",
      "> POST /v2/models/iris/infer HTTP/1.1\n",
      "> Host: 172.21.255.1\n",
      "> User-Agent: curl/7.47.0\n",
      "> Accept: */*\n",
      "> Content-Type: application/json\n",
      "> Content-Length: 94\n",
      "> \n",
      "* upload completely sent off: 94 out of 94 bytes\n",
      "< HTTP/1.1 200 OK\n",
      "< Content-Length: 196\n",
      "< Content-Type: application/json\n",
      "< Date: Sat, 16 Apr 2022 15:53:27 GMT\n",
      "< Seldon-Route: iris_1\n",
      "< Server: envoy\n",
      "< X-Envoy-Upstream-Service-Time: 895\n",
      "< \n",
      "* Connection #0 to host 172.21.255.1 left intact\n",
      "{\"model_name\":\"iris_1\",\"model_version\":\"1\",\"id\":\"0dccf477-78fa-4a11-92ff-4d7e4f1cdda8\",\"parameters\":null,\"outputs\":[{\"name\":\"predict\",\"shape\":[1],\"datatype\":\"INT64\",\"parameters\":null,\"data\":[2]}]}"
     ]
    }
   ],
   "source": [
    "!curl -v http://${INGRESS_IP}/v2/models/iris/infer -H \"Content-Type: application/json\" \\\n",
    "        -d '{\"inputs\": [{\"name\": \"predict\", \"shape\": [1, 4], \"datatype\": \"FP32\", \"data\": [[1, 2, 3, 4]]}]}'"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "hindu-immune",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{\r\n",
      "  \"modelName\": \"iris_1\",\r\n",
      "  \"modelVersion\": \"1\",\r\n",
      "  \"outputs\": [\r\n",
      "    {\r\n",
      "      \"name\": \"predict\",\r\n",
      "      \"datatype\": \"INT64\",\r\n",
      "      \"shape\": [\r\n",
      "        \"1\"\r\n",
      "      ],\r\n",
      "      \"contents\": {\r\n",
      "        \"int64Contents\": [\r\n",
      "          \"2\"\r\n",
      "        ]\r\n",
      "      }\r\n",
      "    }\r\n",
      "  ]\r\n",
      "}\r\n"
     ]
    }
   ],
   "source": [
    "!grpcurl -d '{\"model_name\":\"iris\",\"inputs\":[{\"name\":\"input\",\"contents\":{\"fp32_contents\":[1,2,3,4]},\"datatype\":\"FP32\",\"shape\":[1,4]}]}' \\\n",
    "    -plaintext \\\n",
    "    -import-path ../../apis \\\n",
    "    -proto ../../apis/mlops/v2_dataplane/v2_dataplane.proto \\\n",
    "    ${INGRESS_IP}:80 inference.GRPCInferenceService/ModelInfer"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "centered-tribute",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "service \"myapps\" deleted\r\n",
      "model.mlops.seldon.io \"iris\" deleted\r\n",
      "ingressroute.traefik.containo.us \"iris\" deleted\r\n",
      "middleware.traefik.containo.us \"iris-header\" deleted\r\n"
     ]
    }
   ],
   "source": [
    "!kustomize build config/single-model | kubectl delete -f -"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ecf30391",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.9.10"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
